﻿#include"./Server.hpp"
#include"./Session.hpp"

#include<iostream>


namespace MMFNetwork
{

    Server::Server(
            uint16_t port,
            uint32_t bufferSize,
            const ServerErrorHandler& serverErrorHandler,
            const SessionErrorHandler& errorHandler,
            const SessionStatusHandler& statusHandler,
            const SessionPackageHandler& pkgHanlder,
            const SessionConnectHandler& sessionConnectHandler,
            const std::string& ip
            )
        : mPort(port)
        , mBufferSize(bufferSize)
        , mServerErrirHandler(serverErrorHandler)
        , mErrorHandler(errorHandler)
        , mStatusHandler(statusHandler)
        , mPkgHanlder(pkgHanlder)
        , mSessionConnectHandler(sessionConnectHandler)
        , mIsStop(false)
        , mIp(ip)
    {

    }

    Server::~Server()
    {
        
    }

    void Server::Start()
    {
        //创建监听
        mAcceptor = std::make_unique<ip::tcp::acceptor>(mService, ip::tcp::endpoint(ip::address::from_string(mIp), mPort));

        //开始监听
        StartAccept();

        //线程一定要在第一个异步任务之前，不然mService.run会直接推出
        mWorker = std::make_shared<std::thread>([this](){
            //运行服务，这里时各循环会一直运行，直到所有的异步任务全部完成才会推出
            while(!mIsStop)
            {
                mService.run();
                std::this_thread::sleep_for(std::chrono::milliseconds{10});
            }
        });
    }

    void Server::Stop()
    {
        mIsStop = true;
        std::this_thread::sleep_for(std::chrono::milliseconds{10});
        mService.stop();

        if (mWorker && mWorker->joinable())
        {
            mWorker->join();
            mWorker.reset();
        }
    }

    void Server::StartAccept()
    {
        MMFInetFamily family = MMFInetFamily::V4;
        ip::address addr = ip::address::from_string(mIp);
        if (addr.is_v6())
            family = MMFNetwork::MMFInetFamily::V6;

        //创建Session
        auto session = std::make_shared<Session>(
            mService,
            mBufferSize,
            mErrorHandler,
            mStatusHandler,
            mPkgHanlder,
            family
        );

        //创建好后这里必须关闭一次，新创建的套接字默认是打开的，不然会报错
        //asio每个版本不一样现在变现的行为是不一样的，这里有点坑额
        session->mSocket.close();   

        mAcceptor->async_accept(session->mSocket, [this, session](boost::system::error_code ec){

            if (!ec)
            {
                //启动session,并开始接收包
                session->Start();
                session->mStatus = Status::Connected;       //状态为链接状态
                mSessionConnectHandler(session);
                session->AsyncRecvPackage();
            }
            else 
            {
                mServerErrirHandler(this, ec);
            }

            StartAccept();
        });
    }

    io_context& Server::Context()
    {
        return mService;
    }
}